﻿using Core.Interface;
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Core.CSV
{
    public class CSVDataHelper : ICSVDataHelper
    {
        #region Field
        /// <summary>
        /// Log锁
        /// </summary>
        private object LockObjLog = new object();
        #endregion

        #region Constructor
        public CSVDataHelper() { }
        #endregion

        #region Property
        /// <summary>
        /// 保存路径
        /// </summary>
        public string FilePath { get { return filePath; } set { filePath = value; } }
        private string filePath = string.Empty;

        /// <summary>
        /// 文件夹名称
        /// </summary>
        public string FileFolder
        {
            get { return fileFolder; }
            set { fileFolder = value; }
        }
        private string fileFolder = "Data";

        /// <summary>
        /// 文件名
        /// </summary>
        public string FileName { get { return fileName; } set { fileName = value; } }
        private string fileName = DateTime.Now.ToString("yyyyMMdd");

        /// <summary>
        /// 文件名补充
        /// </summary>
        public string Supplement { get { return supplement; } set { supplement = value; } }
        private string supplement = string.Empty;

        /// <summary>
        /// 自动生成文件名
        /// </summary>
        public bool AutoName { get { return autoName; } set { autoName = value; } }
        private bool autoName = true;

        /// <summary>
        /// 文件后缀
        /// </summary>
        public string FileSuffixe { get { return fileSuffixe; } set { fileSuffixe = value; } }
        private string fileSuffixe = ".csv";

        /// <summary>
        /// 换行符
        /// </summary>
        public string Newline { get { return newLine; } set { newLine = value; } }
        private string newLine = "\r\n";

        /// <summary>
        /// 第一行 标题
        /// </summary>
        public string Title { get; set; }

        /// <summary>
        /// 是否保存
        /// </summary>
        public bool IsSave { get { return isSave; } set { isSave = value; } }
        private bool isSave = true;

        /// <summary>
        /// 保存多少天
        /// </summary>
        public int HowManyDays { get { return howManyDays; } set { howManyDays = value; } }
        private int howManyDays = 15;
        #endregion

        #region Method
        /// <summary>
        /// 初始化
        /// </summary>
        public void Init()
        {
            string appStartupPath = System.IO.Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
            if (string.IsNullOrEmpty(this.filePath))
            {
                this.filePath = string.Format(@"{0}\数据\{1}\", appStartupPath, fileFolder);
            }
            if (!Directory.Exists(filePath))
            {
                Directory.CreateDirectory(filePath);
            }
            DeleteOverFile();
        }

        /// <summary>
        ///  保存数据
        /// </summary>
        /// <param name="content">保存内容</param>
        /// <param name="isAsync">是否异步保存</param>
        public void Save(string content, bool isAsync = true)
        {
            if (IsSave)
            {
                if (isAsync)
                {
                    new Task(() =>
                    {
                        _save(content);
                    }).Start();
                }
                else
                {
                    _save(content);
                }
            }
        }

        /// <summary>
        /// 保存数据到CSV文件
        /// </summary>
        /// <param name="content"></param>
        private void _save(object obj)
        {
            lock (LockObjLog)
            {
                try
                {
                    if (autoName) fileName = DateTime.Now.ToString("yyyyMMdd") + supplement;
                    if (Directory.Exists(filePath) == false)
                    {
                        Directory.CreateDirectory(filePath);
                    }
                    if (!File.Exists(filePath + string.Format(@"{0}{1}", fileName, fileSuffixe)))
                    {
                        File.AppendAllText(FilePath + string.Format(@"{0}{1}", fileName, fileSuffixe), string.IsNullOrEmpty(Title) ? "" : Title + newLine, Encoding.Default);
                    }
                    File.AppendAllText(FilePath + string.Format(@"{0}{1}", fileName, fileSuffixe), obj.ToString() + newLine, Encoding.Default);
                }
                catch (Exception ex)
                {
                    //NotifyG.Error("写入数据记录失败:" + ex.ToString());
                }
            }
        }

        /// <summary>
        /// 将DataTable中数据写入到CSV文件中
        /// </summary>
        /// <param name="dt">提供保存数据的DataTable</param>
        /// <param name="fileName">CSV的文件路径</param>
        public void ConvertDataTableToVSV(DataTable dt, string fullPath)
        {
            FileInfo fi = new FileInfo(fullPath);
            if (!fi.Directory.Exists)
            {
                fi.Directory.Create();
            }
            FileStream fs = new FileStream(fullPath, System.IO.FileMode.Create, System.IO.FileAccess.Write);
            //StreamWriter sw = new StreamWriter(fs, System.Text.Encoding.Default);
            StreamWriter sw = new StreamWriter(fs, System.Text.Encoding.UTF8);
            string data = "";
            //写出列名称
            for (int i = 0; i < dt.Columns.Count; i++)
            {
                data += dt.Columns[i].ColumnName.ToString();
                if (i < dt.Columns.Count - 1)
                {
                    data += ",";
                }
            }
            sw.WriteLine(data);
            //写出各行数据
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                data = "";
                for (int j = 0; j < dt.Columns.Count; j++)
                {
                    string str = dt.Rows[i][j].ToString();
                    str = str.Replace("\"", "\"\"");//替换英文冒号 英文冒号需要换成两个冒号
                    if (str.Contains(',') || str.Contains('"')
                        || str.Contains('\r') || str.Contains('\n')) //含逗号 冒号 换行符的需要放到引号中
                    {
                        str = string.Format("\"{0}\"", str);
                    }

                    data += str;
                    if (j < dt.Columns.Count - 1)
                    {
                        data += ",";
                    }
                }
                sw.WriteLine(data);
            }
            sw.Close();
            fs.Close();
        }

        /// <summary>
        /// 读取csv文件
        /// </summary>
        /// <param name="filePath">路径</param>
        /// <param name="strSplit">行分隔符号</param>
        /// <returns>DataTable</returns>
        public DataTable ReadCSV(string filePath, char strSplit)
        {
            DataTable dt = new DataTable();
            try
            {
                FileStream fs = new FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read);
                StreamReader sr = new StreamReader(fs, Encoding.Default);
                string fileContent = sr.ReadToEnd();
                sr.Close();
                fs.Close();
                sr.Dispose();
                fs.Dispose();
                string[] aryLine = fileContent.Replace("\r\n", ";").Split(';');
                string[] tableHead = aryLine[0].Split(strSplit);
                //标示列数
                if (tableHead != null)
                {
                    //创建列
                    for (int i = 0; i < tableHead.Length; i++)
                    {
                        DataColumn dc = new DataColumn(tableHead[i]);
                        dt.Columns.Add(dc);
                    }
                }
                if (aryLine != null)
                {
                    //创建行
                    for (int i = 1; i < aryLine.Length; i++)
                    {
                        DataRow dr = dt.NewRow();
                        if (!string.IsNullOrEmpty(aryLine[i]))
                        {
                            var col = aryLine[i].Split(strSplit);
                            for (int j = 0; j < tableHead.Length; j++)
                            {
                                dr[j] = col[j];
                            }
                        }
                        dt.Rows.Add(dr);
                    }
                }
            }
            catch (Exception ex)
            {
                //NotifyG.Error(ex.ToString());
            }
            return dt;
        }

        /// <summary>
        /// 读取csv文件
        /// </summary>
        /// <param name="filePath">路径</param>
        /// <returns>string[]</returns>
        public string[] ReadCSV(string filePath)
        {
            try
            {
                FileStream fs = new FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read);
                StreamReader sr = new StreamReader(fs, Encoding.Default);
                string fileContent = sr.ReadToEnd();
                sr.Close();
                fs.Close();
                sr.Dispose();
                fs.Dispose();
                return fileContent.Replace("\r\n", ";").Split(';');
            }
            catch (Exception ex)
            {
                //NotifyG.Error(ex.ToString());
                return null;
            }
        }

        /// <summary>
        /// 删除多余Log文件：支持文件名为"yyyyMMdd.csv"格式
        /// </summary>
        /// <param name="howManyDays"></param>
        private void DeleteOverFile()
        {
            try
            {
                DirectoryInfo theFolder = new DirectoryInfo(FilePath);
                FileInfo[] fileInfo = theFolder.GetFiles();
                foreach (FileInfo NextFile in fileInfo)
                {
                    if (int.Parse(DateTime.Now.AddDays(-HowManyDays).ToString("yyyyMMdd")) >= int.Parse(NextFile.Name.Substring(0, 8)))
                    {
                        File.Delete(FilePath + string.Format(@"{0}", NextFile));
                    }
                }
            }
            catch (Exception ex)
            {
                //NotifyG.Add("删除Log文件失败:" + ex.ToString());
            }
        }

        #endregion
    }
}
